/**
 * @typedef {Object} RequestConfig
 * @property {string} baseURL - 请求基准地址
 * @property {string} url - 接口请求路径
 * @property {*} [data] - 请求参数
 * @property {'GET'|'POST'|'PUT'|'DELETE'|'UPLOAD'} [method='GET'] - 请求方法
 * @property {Object} [header] - 请求头
 * @property {number} [timeout=60000] - 超时时长(ms)
 * @property {boolean} [isLoading=true] - 是否显示loading
 * @property {boolean} [skipAuth=false] - 是否跳过认证
 * @property {number} [retry=0] - 重试次数
 * @property {boolean} [skipErrorToast=false] - 是否跳过错误提示
 */

class WxRequest {
  /** @type {RequestConfig} */
  defaults = {
    baseURL: '',
    url: '',
    data: null,
    method: 'GET',
    header: {
      'Content-Type': 'application/json'
    },
    timeout: 60000,
    isLoading: true,
    skipAuth: false,
    retry: 0,
    skipErrorToast: false
  };

  /** @type {{ request: Function, response: Function }} */
  interceptors = {
    request: (config) => config,
    response: (response) => response
  };

  /** @type {string[]} */
  queue = [];
  timerId = null;

  constructor(params = {}) {
    this.defaults = {
      ...this.defaults,
      ...params
    };
  }

  /**
   * 处理请求数据
   */
  _processRequestData(data, contentType) {
    if (!data) return data;

    if (contentType.includes('x-www-form-urlencoded')) {
      return Object.keys(data)
        .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(data[key])}`)
        .join('&');
    }

    return data;
  }

  /**
   * 显示或隐藏loading
   */
  _toggleLoading(show) {
    console.log(show)
    if (show) {
      this.queue.push('request');
      if (this.queue.length === 1) {
        wx.showLoading({
          title: '加载中...',
          mask: true
        });
      }
    } else {
      this.queue.pop();
      if (this.queue.length === 0) {
        this.timerId = setTimeout(() => {
          wx.hideLoading();
          clearTimeout(this.timerId);
        }, 100);
      }
    }
  }

  /**
   * 发送请求
   */
  request(options = {}) {
    this.timerId && clearTimeout(this.timerId);
    console.log(this.defaults.baseURL)
    // 处理 URL 拼接问题
    if (options.url.startsWith('http')||options.url.startsWith('https')) {
      // 如果已经是完整URL，不再拼接baseURL
      options.url = options.url.replace(this.defaults.baseURL, '');
    }
    const config = {
      ...this.defaults,
      ...options,
      url: this.defaults.baseURL + (options.url || ''),
      header: {
        ...this.defaults.header,
        ...(options.header || {})
      }
    };
    console.log(config)
    config.data = this._processRequestData(
      config.data,
      config.header['Content-Type']
    );

    const interceptedConfig = this.interceptors.request(config);

    if (interceptedConfig.isLoading && interceptedConfig.method !== 'UPLOAD') {
      this._toggleLoading(true);
    }

    return new Promise((resolve, reject) => {
      if (interceptedConfig.method === 'UPLOAD') {
        this._uploadFile(interceptedConfig, resolve, reject);
      } else {
        this._normalRequest(interceptedConfig, resolve, reject);
      }
    });
  }

  _normalRequest(config, resolve, reject) {
    wx.request({
      ...config,
      success: (res) => {
        const response = this._buildResponse(res, config, true);
        resolve(this.interceptors.response(response));
      },
      fail: (err) => {
        const response = this._buildResponse(err, config, false);
        reject(this.interceptors.response(response));
      },
      complete: () => {
        if (config.isLoading) {
          this._toggleLoading(false);
        }
      }
    });
  }

  _uploadFile(config, resolve, reject) {
    wx.uploadFile({
      ...config,
      success: (res) => {
        try {
          res.data = JSON.parse(res.data);
        } catch (e) {
          console.error('解析上传响应失败:', e);
        }
        const response = this._buildResponse(res, config, true);
        resolve(this.interceptors.response(response));
      },
      fail: (err) => {
        const response = this._buildResponse(err, config, false);
        reject(this.interceptors.response(response));
      },
      complete: () => {
        if (config.isLoading) {
          this._toggleLoading(false);
        }
      }
    });
  }

  _buildResponse(res, config, isSuccess) {
    return {
      ...res,
      config,
      isSuccess
    };
  }

  // 快捷方法
  get(url, data = {}, config = {}) {
    return this.request({
      url,
      data,
      method: 'GET',
      ...config
    });
  }

  delete(url, data = {}, config = {}) {
    return this.request({
      url,
      data,
      method: 'DELETE',
      ...config
    });
  }

  post(url, data = {}, config = {}) {
    console.log(config)
    return this.request({
      url,
      data,
      method: 'POST',
      ...config
    });
  }

  put(url, data = {}, config = {}) {
    return this.request({
      url,
      data,
      method: 'PUT',
      ...config
    });
  }

  upload(url, filePath, name = 'file', config = {}) {
    return this.request({
      url,
      filePath,
      name,
      method: 'UPLOAD',
      ...config
    });
  }

  all(...promises) {
    return Promise.all(promises);
  }
}
function removeSpecificDuplicates(str, targetChar) {
  // 转义特殊字符
  const escapedChar = targetChar.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
  const regex = new RegExp(`(${escapedChar})(?=.*\\1)`, 'g');
  return str.replace(regex, '');
}

module.exports = WxRequest;